//
//  BaseAFNEngine.m
//  BeiGuo
//
//  Created by Yaping Liu on 16/5/7.
//  Copyright © 2016年 com.dlnu.*. All rights reserved.
//

#import "BaseEngine.h"
#import "WKAlertView.h"
#import "NSObject+KZExtension.h"
#import "NSString+MKNetworkKitAdditions.h"

static NSString * const kProtocolLocalizedDescription = @"网络连接错误";
static NSString * const secret =@"1248909376";

@interface BaseEngine ()


@property (strong, nonatomic) NSString *decodeKey;
@property (strong, nonatomic) NSString *deviceId;
@property (strong, nonatomic) NSString *appVersion;

@end

@implementation BaseEngine

+ (BaseEngine *)sharedEngine
{
    static BaseEngine *sharedSingleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
        sharedSingleton = [[BaseEngine alloc] init];
    });
    return sharedSingleton;
}


- (instancetype)init
{
    if(self = [super init]){
        
        self.deviceId = mydeviceUniqueIdentifier();
        self.appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
        self.httpMethod = @"GET";
        self.needLogin = YES;
    }
    return self;
}

- (void)setRequestPost
{
    self.httpMethod = @"POST";
}

- (NSURLSessionDataTask *)RunRequest:(NSMutableDictionary *)dict
                                path:(NSString *)path
                   completionHandler:(ResponseBlock)completionBlock
                        errorHandler:(AFNErrorBlock)errorBlock
                       finishHandler:(FinishBlock)finishBlock
{
    
    return [self RunRequest:dict path:path useSSL:NO completionHandler:completionBlock errorHandler:errorBlock finishHandler:finishBlock];
}
- (NSURLSessionDataTask* )RunRequest:(NSMutableDictionary *)  dict
                                path:(NSString *)path
                              useSSL:(BOOL)useSSL
                   completionHandler:(ResponseBlock)completionBlock
                        errorHandler:(AFNErrorBlock)errorBlock
                       finishHandler:(FinishBlock)finishBlock;
{
    
    
    NSMutableDictionary *paramDict = [self obtainParametersDictionaryWithDic:dict];
    
    
//    NSMutableString *urlString = [NSMutableString stringWithFormat:@"%@",kServerDomain];
    
//    path = _S(@"%@/%@", urlString, path);
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager.requestSerializer setValue:@"gzip, deflate, sdch" forHTTPHeaderField:@"Accept-Encoding"];
    [manager.requestSerializer setValue:@"zh,CN" forHTTPHeaderField:@"Accept-Language"];
    [manager.requestSerializer setValue:@"text/json" forHTTPHeaderField:@"Content-Type"];
    
    AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
    serializer.acceptableContentTypes = [NSSet setWithObjects:@"text/json",@"text/html",@"application/json", nil];
    manager.responseSerializer = serializer;
    
    
    NSURLSessionDataTask *task = nil;
    
    
    IMP_BLOCK_SELF(BaseEngine);
    
    task = [manager POST:path parameters:paramDict constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        if (paramDict) {
            NSError *error;
            NSData *jsonData = [NSJSONSerialization dataWithJSONObject:paramDict options:0 error:&error];
            NSAssert(jsonData, @"Failure building JSON: %@", error);
            DLog(@"Json Data Image Upload %@",jsonData);
            NSAssert(jsonData, @"Failure building JSON: %@", error);
            
            
            NSDictionary *jsonHeaders = @{@"Content-Disposition" : @"form-data; name=\"parameters\"",
                                          @"Content-Type"        : @"application/json",
                                          @"Accept"              : @"application/json"};
            [formData appendPartWithHeaders:jsonHeaders body:jsonData];
        }
        
        for (NSString *key in [block_self.postDict allKeys])
        {
            [formData appendPartWithFileData:[block_self.postDict valueForKeyPath:key] name:key fileName:@"content" mimeType:@"application/octet-stream"];
            
        }
        
        [block_self.postDict removeAllObjects];
        
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [block_self analysisDataWithObject:responseObject path:task.currentRequest.description completionHandler:completionBlock finishHandler:finishBlock];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        DLog(@"===>>>%@",error);
        if (error.code==NSURLErrorCancelled) {
            error = [[NSError alloc] initWithDomain:@"" code:999 userInfo:nil];
        }
        else{
            error = [[NSError alloc] initWithDomain:kProtocolLocalizedDescription code:201 userInfo:nil];
        }
        if (errorBlock) {
            errorBlock(error);
        }
    }];
    
    
    
    
    return task;
    
    
    
}
#pragma mark - File Download
- (void)DownloadFileFrom:(NSString *)remoteURL
                  toFile:(NSString *)filePath
       completionHandler:(DownloadBlock)completionBlock
            errorHandler:(AFNErrorBlock)errorBlock
{
    
    IMP_BLOCK_SELF(BaseEngine);
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:remoteURL]];
    
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    NSURLSessionDownloadTask *downloadtask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        if (block_self.delegate != nil && [block_self.delegate respondsToSelector:@selector(completePercentageWithFloat:)]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [block_self.delegate completePercentageWithFloat:downloadProgress.fractionCompleted];
            });
        }
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        
        return [NSURL fileURLWithPath:filePath];
        
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        
        if (error) {
            if (errorBlock) {
                errorBlock(error);
            }
            
        }else{
            if (completionBlock) {
                completionBlock([filePath absoluteString]);
            }
        }
    }];
    
    [downloadtask resume];
    
}
#pragma mark - Data Upload
- (NSURLSessionDataTask *)uploadDataWithPath:(NSString *)path
                                  parameters:(NSMutableDictionary *)parameters
                                     manager:(AFHTTPSessionManager *)manager
                           completionHandler:(ResponseBlock)completionBlock
                                errorHandler:(AFNErrorBlock)  errorBlock
                               finishHandler:(FinishBlock)finishBlock
{
    
    IMP_BLOCK_SELF(BaseEngine)
    NSURLSessionDataTask *task = [manager POST:path parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        for (NSString *key in [block_self.postDict allKeys])
        {
            [formData appendPartWithFileData:[block_self.postDict valueForKeyPath:key] name:key fileName:@"imageData" mimeType:@"application/octet-stream"];
            
        }
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        if (block_self.delegate != nil && [block_self.delegate respondsToSelector:@selector(completePercentageWithFloat:)]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [block_self.delegate completePercentageWithFloat:uploadProgress.fractionCompleted];
            });
        }    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            [block_self analysisDataWithObject:responseObject path:task.currentRequest.description completionHandler:completionBlock finishHandler:finishBlock];
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            if (error.code==NSURLErrorCancelled) {
                error = [[NSError alloc] initWithDomain:@"" code:999 userInfo:nil];
            }
            else{
                error = [[NSError alloc] initWithDomain:kProtocolLocalizedDescription code:201 userInfo:nil];
            }
            if (errorBlock) {
                errorBlock(error);
            }
        }];
    return task;
}

#pragma mark - File Upload
- (NSURLSessionDataTask *)uploadFileUrlWithPath:(NSString *)path
                                     parameters:(NSMutableDictionary *)parameters
                                        manager:(AFHTTPSessionManager *)manager
                              completionHandler:(ResponseBlock)completionBlock
                                   errorHandler:(AFNErrorBlock)  errorBlock
                                  finishHandler:(FinishBlock)finishBlock
{
    
    IMP_BLOCK_SELF(BaseEngine)
    NSURLSessionDataTask *task = [manager POST:path parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        for (NSString *key in [block_self.postFileDict allKeys])
        {
            [formData appendPartWithFileURL:[NSURL fileURLWithPath:[block_self.postFileDict valueForKeyPath:key]] name:key error:nil];
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        if (block_self.delegate != nil && [block_self.delegate respondsToSelector:@selector(completePercentageWithFloat:)]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [block_self.delegate completePercentageWithFloat:uploadProgress.fractionCompleted];
            });
        }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        [block_self analysisDataWithObject:responseObject path:task.currentRequest.description completionHandler:completionBlock finishHandler:finishBlock];
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        error = [[NSError alloc] initWithDomain:kProtocolLocalizedDescription code:201 userInfo:nil];
        if (errorBlock) {
            errorBlock(error);
        }
    }];
    return task;
}
#pragma mark - Parser Data
- (void)analysisDataWithObject:(id)responseObject
                          path:(NSString *)path
             completionHandler:(ResponseBlock)completionBlock
                 finishHandler:(FinishBlock)finishBlock
{
    
    id reDict = responseObject;
    DLog(@"%@ ===>>>> %@",path,reDict);
    
    //0-normal or none
    int statusCode = [[reDict objectForKey:@"code"] intValue];
    if (statusCode == 201 || statusCode == 202) {
        //单点登录
        [UserConfig setUserInfo:nil];
        [UserConfig setUserToken:nil];
        uialer *alert = [[CTAlertView shareCTAlert] initWithTitle:nil message:@"你的账号已在另一台手机登录" delegateBlock:^(UIAlertView *alert, int index) {
            if (index==0) {
                exit(0);
            } else {
                [theApp initRootViewController];
            }
        } titles:@"退出应用",@"重新登录", nil];
        [alert show];
        
    } else if (statusCode == 200 || reDict==nil){
        dispatch_async(dispatch_get_main_queue(), ^{
            if (completionBlock) {
                completionBlock(reDict);
            }
        });
        reDict = nil;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if (finishBlock) {
            finishBlock(reDict);
        }
    });
}
#pragma mark - Obtain Parameters

- (NSMutableDictionary *)obtainParametersDictionaryWithDic:(NSMutableDictionary *)dict
{
//    if (dict==nil) {
//        return nil;
//    }
    NSMutableDictionary *paramDict = [[NSMutableDictionary alloc] initWithDictionary:dict];
    
    NSString *token = [UserConfig getUserToken];
    if (token) {
        [paramDict setObject:token forKey:@"token"];
        [paramDict setObject:_S(@"%.0f",[UserConfig getUserInfo].uid) forKey:@"uid"];
//        [paramDict setObject:_S(@"%d",[UserConfig getUserInfo].type) forKey:@"type"];
    }
    NSArray *keys = [dict allKeys];
    NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1 compare:obj2];
    }];
    
    NSMutableString *paramStr = [[NSMutableString alloc] init];
    
    for (NSString *key in sortedArray) {
        NSString *encodeStr = _S(@"%@",[paramDict objectForKey:key]);
        
        [paramStr appendString:[NSString stringWithFormat:@"&%@=%@",key,StringIsNullRetBlank(encodeStr)]];
        
        [paramDict setObject:StringIsNullRetBlank(encodeStr) forKey:key];
    }
    double timestamp = [[NSDate date] timeIntervalSince1970]/1000;
    long rand = [self getRandomNumber:100000 to:999999];
    NSString * keyBaseString = _S(@"%@%.0f%ld",secret,timestamp,rand);
    NSString * keyString = [[keyBaseString md5] base64Encode];
    
    [paramDict setObject:_S(@"%.0f",timestamp) forKey:@"timestamp"];
    [paramDict setObject:_S(@"%ld",rand) forKey:@"rand"];
    [paramDict setObject:keyString forKey:@"signature"];
    
    return paramDict;
}

-(long)getRandomNumber:(long)from to:(long)to {
    return (long)(from + (arc4random() % (to - from + 1)));
}

#pragma mark - Cancel Net Request
- (void)cancelOperation:(NSURLSessionDataTask *)task {
    showIndicator(NO, nil);
    if (task) {
        [task cancel];
    }
}

#pragma mark - lazy
- (NSMutableDictionary *)postDict{
    if (!_postDict) {
        _postDict = [[NSMutableDictionary alloc] init];
    }
    return _postDict;
}

- (NSMutableDictionary *)postFileDict{
    if (!_postFileDict) {
        _postFileDict = [[NSMutableDictionary alloc] init];
    }
    return _postFileDict;
}


@end
